home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Core / Sources / UFailure.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  10.4 KB  |  424 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UFailure.cp
  3. // Copyright © 1985-96 by Apple Computer, Inc. All rights reserved.
  4. //----------------------------------------------------------------------------------------
  5.  
  6. #ifndef __UFAILURE__
  7. #include "UFailure.h"
  8. #endif
  9.  
  10. // MacApp
  11.  
  12. #ifndef __UDEBUG__
  13. #include "UDebug.h"
  14. #endif
  15.  
  16. #ifndef __UCOREUTILITIES__
  17. #include "UCoreUtilities.h"
  18. #endif
  19.  
  20. #ifndef __UTHEDEBUGGER__
  21. #include "UTheDebugger.h"
  22. #endif
  23.  
  24. // Toolbox
  25.  
  26. #ifndef __ERRORS__
  27. #include <Errors.h>
  28. #endif
  29.  
  30. #ifndef __LOWMEM__
  31. #include <LowMem.h>
  32. #endif
  33.  
  34. #ifndef __MEMORY__
  35. #include <Memory.h>
  36. #endif
  37.  
  38. #ifndef __RESOURCES__
  39. #include <Resources.h>
  40. #endif
  41.  
  42. #ifndef __PROCESSES__
  43. #include <Processes.h>
  44. #endif
  45.  
  46. // ANSI
  47.  
  48. #ifndef __STDIO__
  49. #include <stdio.h>
  50. #endif
  51.  
  52. //----------------------------------------------------------------------------------------
  53. // static data members
  54. //----------------------------------------------------------------------------------------
  55. FailInfoPtr FailInfo::gTopHandler;
  56.  
  57.  
  58. //----------------------------------------------------------------------------------------
  59. // GLOBAL Variables
  60. //----------------------------------------------------------------------------------------
  61.  
  62. #if qDebug
  63. static MAName pWho;                            // used serially. Avoids putting it on stack
  64. #endif
  65.  
  66. //----------------------------------------------------------------------------------------
  67. // Assertion: 
  68. //----------------------------------------------------------------------------------------
  69. #pragma segment MAFailureRes
  70.  
  71. void Assertion(const Boolean condition,
  72.                const CStr255& 
  73. #if qDebug
  74.                                 description
  75. #endif
  76.                                            )
  77. {
  78.     if (!condition)
  79.     {
  80. #if qDebug
  81.         GetCallersMethodName(pWho);
  82.         fprintf(stderr, "Assertion failed in " + pWho + ": " + description + "\n");
  83. #endif
  84.         Failure(minErr, 0);
  85.     }
  86. } // Assertion 
  87.  
  88. //----------------------------------------------------------------------------------------
  89. // FailMemError: 
  90. //----------------------------------------------------------------------------------------
  91. #pragma segment MAFailureRes
  92.  
  93. long BuildMessage(short lowWord, short highWord)
  94. {
  95.     return ((long)highWord << 16) | lowWord;
  96. }
  97.  
  98. //----------------------------------------------------------------------------------------
  99. // FailMemError: 
  100. //----------------------------------------------------------------------------------------
  101. #pragma segment MAFailureRes
  102.  
  103. void FailMemError()
  104. {
  105.     OSErr e = MemError();
  106.  
  107.     if (e != noErr)
  108.         Failure(e, 0);
  109. } // FailMemError 
  110.  
  111. //----------------------------------------------------------------------------------------
  112. // FailNewMessage: 
  113. //----------------------------------------------------------------------------------------
  114. #pragma segment MAFailureRes
  115.  
  116. void FailNewMessage(OSErr error,
  117.                     long oldMessage,
  118.                     long newMessage)
  119. {
  120.     Failure(error, oldMessage ? oldMessage : newMessage);
  121. } // FailNewMessage 
  122.  
  123. //----------------------------------------------------------------------------------------
  124. // FailNIL: 
  125. //----------------------------------------------------------------------------------------
  126. #pragma segment MAFailureRes
  127.  
  128. void FailNIL(void* p)
  129. {
  130.     if (!p)
  131.         Failure(memFullErr, 0);
  132. } // FailNIL 
  133.  
  134. //----------------------------------------------------------------------------------------
  135. // FailNILResource: 
  136. //----------------------------------------------------------------------------------------
  137. #pragma segment MAFailureRes
  138.  
  139. void FailNILResource(Handle r)
  140. {
  141.     if (!r)
  142.     {
  143.         OSErr e = ResError();
  144.         if (e == noErr)
  145.             e = resNotFound;
  146.         Failure(e, 0);
  147.     }
  148. } // FailNILResource 
  149.  
  150. //----------------------------------------------------------------------------------------
  151. // FailOSErr: 
  152. //----------------------------------------------------------------------------------------
  153. #pragma segment MAFailureRes
  154.  
  155. void FailOSErr(OSErr error)
  156. {
  157.     if (error != noErr)
  158.         Failure(error, 0);
  159. } // FailOSErr 
  160.  
  161. //----------------------------------------------------------------------------------------
  162. // FailOSAError: 
  163. //----------------------------------------------------------------------------------------
  164. #pragma segment MAFailureRes
  165.  
  166. void FailOSAError(long error)
  167. {
  168.     if (error != noErr)
  169.         Failure((OSErr) error, 0);
  170. } // FailOSAError 
  171.  
  172. //----------------------------------------------------------------------------------------
  173. // FailResError: 
  174. //----------------------------------------------------------------------------------------
  175. #pragma segment MAFailureRes
  176.  
  177. void FailResError()
  178. {
  179.     OSErr e = ResError();
  180.  
  181.     if (e != noErr)
  182.         Failure(e, 0);
  183. } // FailResError 
  184.  
  185. //----------------------------------------------------------------------------------------
  186. // Failure: 
  187. //----------------------------------------------------------------------------------------
  188. #pragma segment MAFailureRes
  189.  
  190. void Failure(OSErr error, long message)
  191. {
  192.     FailInfoPtr pf = FailInfo::gTopHandler;
  193.     if (pf)
  194.     {
  195.         do
  196.         {
  197.             // pop the stack first, because calling the handler is likely to result in a call
  198.             // to Failure
  199.             FailInfo::gTopHandler = pf->nextInfo;
  200.  
  201. #if qDebug
  202.             if (pf->installed && pf->cleanupProc)
  203.                 ProgramBreak("Use SetCleanupProc or Try, not both");
  204.             
  205.             pf->installed = FALSE;                
  206.             if (DebugCanWriteLn() && (((error != noErr) && (error != userCanceledErr)) || gIntenseDebugging))// only show 0 errors if _really_ looking
  207.             {
  208.                 GetCallersMethodName(pWho);
  209.                 fprintf(stderr, "Failure signaled by: %s\n", (const char*)pWho);
  210.                 fprintf(stderr, "        error: %1d message: %1d (%1d/%1d)\n", error, message, message >> 16, message & 0x0000FFFF);
  211.             }
  212. #endif
  213.  
  214.             pf->error = error;
  215.             pf->message = message;
  216.             
  217.             // Go execute the failure handler
  218.             
  219.             if (pf->cleanupProc)
  220.                 (*(pf->cleanupProc))(pf->cleanupContext);
  221.             else
  222.                 longjmp(pf->savedState, 0);
  223.             
  224.             // If a cleanupProc was specified, we'll fall through to here and loop
  225.             // to the next failure handler (less overhead than recursing)
  226.         }
  227.         while ((pf = FailInfo::gTopHandler) != NULL);
  228.     }
  229.     else
  230.     {
  231. #if qDebug
  232.         ProgramBreak("Failure called, but no handler!");
  233. #endif
  234.         // The following ExitToShell allows the application to fail somewhat gracefully
  235.         // in the case that an allocation request has failed during static initialization.
  236.         ExitToShell();
  237.     }
  238. } // Failure 
  239.  
  240. //----------------------------------------------------------------------------------------
  241. // ProgramBreak: 
  242. //----------------------------------------------------------------------------------------
  243. #pragma segment MAFailureRes
  244.  
  245. void ProgramBreak(const CStr255& grievance)
  246. {
  247.     CStr255 report = grievance + "\n";
  248.     
  249. #if qDebug || qTheDebugger
  250. #if !defined(__MWERKS__) || (TypeOfCWDebugging != kxUseSTE)
  251.     fflush(stderr);
  252. #endif
  253. #endif
  254.  
  255. #if qDebug
  256.     if ((gCurrentDebugger == kxSourceBug) || (gCurrentDebugger == kxVooDoo) ||
  257.         (gCurrentDebugger == kxSade))
  258.         SysBreakFunc(report);
  259.     else        
  260. #endif
  261. #if qTheDebugger
  262.     if (gExtDbgr_Info.isBeingDebugged || TheDbgr_IsInstalled())
  263.         SysBreakFunc(report);
  264.     else        
  265. #endif
  266.         DebugStr(report);
  267. }
  268.  
  269. //----------------------------------------------------------------------------------------
  270. // ProgramReport: 
  271. //----------------------------------------------------------------------------------------
  272. #pragma segment MAFailureRes
  273.  
  274. void ProgramReport(const CStr255& grievance,
  275.                   const Boolean breakInDebugger)
  276. {
  277.     CStr255 report = grievance + "\n";
  278.     
  279. #if qDebug || qTheDebugger
  280. #if !defined(__MWERKS__) || (TypeOfCWDebugging != kxUseSTE)
  281.     fflush(stderr);
  282. #endif
  283. #endif
  284.  
  285. #if qDebug
  286.     if ((gCurrentDebugger == kxSourceBug) || (gCurrentDebugger == kxVooDoo) ||
  287.         (gCurrentDebugger == kxSade))
  288.     {
  289.         if (breakInDebugger)
  290.             SysBreakStr(report);
  291.         else
  292.             SysBreakFunc(report);
  293.     }
  294.     else        
  295. #endif
  296. #if qTheDebugger
  297.     if (gExtDbgr_Info.isBeingDebugged || TheDbgr_IsInstalled())
  298.     {
  299.         if (breakInDebugger)
  300.             SysBreakStr(report);
  301.         else
  302.             SysBreakFunc(report);
  303.     }
  304.     else        
  305. #endif
  306.     {
  307.         if (!breakInDebugger)
  308.             report += ";g";
  309.         DebugStr(report);
  310.     }
  311. }
  312.  
  313. //----------------------------------------------------------------------------------------
  314. // FailInfo::~FailInfo 
  315. //----------------------------------------------------------------------------------------
  316. #pragma segment MAFailureRes
  317.  
  318. #if qDebug
  319. FailInfo::~FailInfo()
  320. {
  321.     if (installed)
  322.         ProgramBreak("You forgot to call success for your failure handler");
  323. }
  324. #endif
  325.  
  326. //----------------------------------------------------------------------------------------
  327. // FailInfo::Install 
  328. //----------------------------------------------------------------------------------------
  329. #pragma segment MAFailureRes
  330.  
  331. FailInfo* FailInfo::Install()
  332. {
  333.     nextInfo = gTopHandler;
  334.     gTopHandler = this;
  335. #if qDebug
  336.     installed = TRUE;
  337. #endif
  338.     
  339.     return this;
  340. }
  341.  
  342. //----------------------------------------------------------------------------------------
  343. // FailInfo::Success 
  344. //----------------------------------------------------------------------------------------
  345. #pragma segment MAFailureRes
  346.  
  347. #if qDebug
  348. void FailInfo::Success()
  349. {
  350.     if (gTopHandler != this)
  351.     {
  352.         CStr255 msg;
  353.     
  354.         fprintf(stderr, "gTopHandler: %p, parameter: %p\n", gTopHandler, this);
  355.         msg = "Problem with Success: ";
  356.         if (HandlerExists())
  357.             msg += "too few ";
  358.         else
  359.             msg += "too many ";
  360.         msg += "calls to Success";
  361.         ProgramBreak(msg);
  362.     }
  363.  
  364.     installed = FALSE;
  365.  
  366.     gTopHandler = nextInfo;
  367. } // Success 
  368. #endif
  369.  
  370.  
  371. //----------------------------------------------------------------------------------------
  372. // FailInfo::Reset 
  373. //----------------------------------------------------------------------------------------
  374. #pragma segment MAFailureRes
  375.  
  376. void FailInfo::Reset()
  377. {
  378.     nextInfo = NULL;
  379.     cleanupProc = NULL;
  380.     cleanupContext = NULL;
  381.     message = 0;
  382.     error = noErr;
  383. #if qDebug
  384.     installed = FALSE;
  385. #endif
  386. }
  387.  
  388. //----------------------------------------------------------------------------------------
  389. // FailInfo::SetCleanupProc 
  390. //----------------------------------------------------------------------------------------
  391. #pragma segment MAFailureRes
  392.  
  393. void FailInfo::SetCleanupProc(FailureCleanupProc theCleanupProc, void* itsContext)
  394. {
  395.     nextInfo = gTopHandler;
  396.     gTopHandler = this;
  397.     cleanupProc = theCleanupProc;
  398.     cleanupContext = itsContext;
  399. }
  400.  
  401. //----------------------------------------------------------------------------------------
  402. // FailInfo::HandlerExists 
  403. //----------------------------------------------------------------------------------------
  404. #pragma segment MAFailureRes
  405.  
  406. Boolean FailInfo::HandlerExists() const
  407. {
  408.     FailInfoPtr pf = gTopHandler;
  409.  
  410.     while (pf)
  411.     {
  412.         if (pf == this)
  413.             return TRUE;
  414.         pf = pf->nextInfo;
  415.     }
  416.  
  417.     return FALSE;
  418. } // HandlerExists 
  419.  
  420. //----------------------------------------------------------------------------------------
  421. // End of UFailure.cp
  422.  
  423. #pragma segment Inline
  424.